/* 用于加载配置文件 */

#ifndef __MY_CONFIG__
#define __MY_CONFIG__
#include "FileUtil.hpp"
#include "JsonUtil.hpp"
#include "log.hpp"
#include <mutex>
#define CONF_PATH "./cloud.conf"

extern Log my_log;
namespace cloud
{
class Config
{
private:
    static Config* _instance;
    static std::mutex _mtx;
    Config(const Config& c) = delete;
    Config& operator=(const Config& c) = delete;

    Config() 
    {
        if(loadFiles() == false)    delInstance();
    }

    // 从配置文件中加载数据，放到各个属性中
    bool loadFiles()
    {   
        // 打开文件
        cloud::FileUtil fu(CONF_PATH);
        std::string content;
        
        if(fu.getFullContent(&content) == false) {
            my_log(ERROR, "getFullContent error in bool loadFiles()\n");
            // std::cerr << "getFullContent error!\nbool loadFiles()\n";
            return false;
        }

        // json转换
        Json::Value root;
        if(cloud::JsonUtil::unserialize(content, &root) == false) {
            std::cerr << "unserialize error!\nbool loadFiles()\n";
            return false;
        }

        // 初始化
        _serverIp = root["serverIp"].asString();
        _serverPort = root["serverPort"].asInt();
        _hotTime = root["hotTime"].asInt64();
        _urlDownPre = root["pathPre"].asString();
        _rarSuf = root["rarSuf"].asString();
        _ulPath = root["ulPath"].asString();
        _rarPath = root["rarPath"].asString();
        _backups = root["backups"].asString();
        _dbHost = root["dbHost"].asString();
        _dbPort = root["dbPort"].asInt64();
        _dbUser = root["dbUser"].asString();
        _dbPasswd = root["dbPass"].asString();
        _dbName = root["dbName"].asString();

        return true;
    }
private:
    std::string _serverIp;  // 服务器访问 IP 地址  
    int _serverPort;        // 服务器访问端⼝ 
    std::time_t _hotTime;   // 热点判断时间
    std::string _urlDownPre;// URL下载路径前缀
    std::string _rarSuf;    // 压缩包后缀名称
    std::string _ulPath;    // 上传文件存放的路径(这里指的是文件夹)
    std::string _rarPath;   // 压缩文件存放的路径(这里指的是文件夹)
    std::string _backups;   // 备份文件
    // 数据库相关属性
    std::string _dbHost;    // 数据库主机地址
    int _dbPort;            // 数据库端口
    std::string _dbUser;    // 数据库用户名
    std::string _dbPasswd;  // 数据库密码
    std::string _dbName;    // 数据库名
public:
    // 获取实例
    static Config* getInstance()
    {
        if(_instance == nullptr) {      
            // _instance为null时，才有加锁解锁的必要。外面多加一层判断可以防止每次getInstance()时都要申请锁
            std::unique_lock<std::mutex> lck(_mtx);
            if(_instance == nullptr) {
                _instance = new Config();
            }
        }
        return _instance;
    }

    // 删除实例
    static void delInstance()
    {
        if(_instance != nullptr) {
            my_log(INFO, "static void delInstance()\n");
            // std::cout << "log: static void delInstance()\n";
            delete _instance;
            _instance = nullptr;
        }
    }

    const std::string& getServerIp() const { return _serverIp; }

    int getServerPort() const { return _serverPort; }

    std::time_t getHotTime() const { return _hotTime; }

    const std::string& getDownPre() { return _urlDownPre; }

    const std::string& getRarSuf() { return _rarSuf; }

    const std::string&getUlPath() { return _ulPath; }

    const std::string& getRarPath() { return _rarPath; }

    const std::string& getBackups() { return _backups; } 

    const std::string& getDbHost() { return _dbHost; }
    
    int getDbPort() { return _dbPort; }

    const std::string& getDbUser() { return _dbUser; }

    const std::string& getDbPasswd() { return _dbPasswd; }

    const std::string& getDbName() { return _dbName; }

};
Config* Config::_instance = nullptr;
std::mutex Config::_mtx;
}

#endif